package com.example.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.example.common.RedisConstants;
import com.example.common.enums.ResultCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.entity.*;
import com.example.exception.CustomException;
import com.example.mapper.BusinessMapper;
import com.example.utils.RedisUtils;
import com.example.utils.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.sf.jsqlparser.expression.StringValue;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author: 康伟奇
 * @date: 2023 - 11 - 03 14:09
 **/
@Service
public class BusinessService {
    @Autowired
    private BusinessMapper businessMapper;

    @Resource
    private CommentService commentService;

    @Resource
    private OrdersService ordersService;

    @Resource
    private OrdersItemService ordersItemService;

    @Resource
    private HistoryService historyService;

    @Resource
    private BannerService bannerService;

    @Resource
    private GoodsService goodsService;

    @Resource
    private CategoryService categoryService;


    @Resource
    private CollectService collectService;

    //检查商家权限 检测是否可以新增数据
    public void checkBusinessAuth(){
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.BUSINESS.name().equals(currentUser.getRole())){
            //如果是商家
            Business business = selectById(currentUser.getId());
            if (!"通过".equals(business.getStatus())){
                throw new CustomException(ResultCodeEnum.NO_AUTH);
            }
        }
    }


    /**
     * 查询所有商家
     * @param business 查询条件
     * @return 返回Business的集合
     */
    public List<Business> selectAll(Business business) {
        List<Business> businessList = new ArrayList<>();
        if (business == null){
            //不是按照条件进行查询则使用缓存进行查询
            businessList = RedisUtils.getCacheObject(RedisConstants.REDIS_ALL_BUSINESS_KEY);
        }
        System.out.println(businessList);
        if (CollUtil.isEmpty(businessList)){
            businessList = businessMapper.selectAll(business);
            for (Business b : businessList) {
                wrapBusiness(b);
                RedisUtils.setCacheObject(RedisConstants.REDIS_BUSINESS_KEY+b.getId(),b);
            }
            RedisUtils.setCacheObject(RedisConstants.REDIS_ALL_BUSINESS_KEY,businessList);
        }

        return businessList;
    }

    private void wrapBusiness(Business b){
        List<Comment> commentList = commentService.selectByBusinessId(b.getId());
        double allScore = commentList.stream().map(Comment::getStar).reduce(Double::sum).orElse(0D) + 5D;
        double score = BigDecimal.valueOf(allScore)
                .divide(BigDecimal.valueOf(commentList.size() + 1),1,BigDecimal.ROUND_UP).doubleValue();
        b.setScore(score);

        //查出所有有效订单
        List<Orders> ordersList = ordersService.selectUsageByBusinessId(b.getId());
        int nums = 0;
        for (Orders orders : ordersList) {
            List<OrdersItem> ordersItemList = ordersItemService.selectByOrderId(orders.getId());
            //聚合函数查出订单的商品数量
            nums  += ordersItemList.stream().map(OrdersItem::getNum).reduce(Integer::sum).orElse(0);
        }
        b.setNums(nums);
    }

    /**
     * 根据id查询单个商家
     * @param id 序号
     * @return Business对象
     */
    public Business selectById(Integer id) {
        Business business = RedisUtils.getCacheObject(RedisConstants.REDIS_BUSINESS_KEY + id);
        if (business == null){
            business = this.selectByBasicBusinessById(id);
        }
        if (business != null){
            Account currentUser = TokenUtils.getCurrentUser();
            Collect collect = collectService.selectByUserIdAndBusinessId(currentUser.getId(), id);
            business.setIsCollect(collect != null);
        }

        //当用户点击商店时检查数据库中是否有数据，如果之前看过则更新时间，否则就新增到history表中
        if (RoleEnum.USER.name().equals(TokenUtils.getCurrentUser().getRole()) || RoleEnum.RIDER.name().equals(TokenUtils.getCurrentUser().getRole())){
            History history = historyService.selectByBusinessIdAndUserId(id,TokenUtils.getCurrentUser().getId());
            if (history != null){
                String now = DateUtil.now();
                history.setTime(now);
                historyService.updateById(history);
            }else {
                History h = new History();
                h.setBusinessId(id);
                h.setUserId(TokenUtils.getCurrentUser().getId());
                h.setTime(DateUtil.now());
                historyService.add(h);
            }
        }
        return business;
    }

    /**
     * 查询基础的商家信息
     * @param id 商家id
     * @return 商家信息
     */
    public Business selectByBasicBusinessById(Integer id){
        Business params = new Business();
        params.setId(id);
        List<Business> list = this.selectAll(params);
        return list.size() == 0 ? null : list.get(0);
    }

    /**
     * 根据账号查询
     * @param username 用户名
     * @return 商家对象
     */
    public Business selectByUserName(String username){
        Business params = new Business();
        params.setUsername(username);
        List<Business> list = this.selectAll(params);
        return list.size() == 0 ? null : list.get(0);
    }

    /**
     * 分页查询所有商家
     * @param business 可能需要的查询条件
     * @param pageNum   当前页码
     * @param pageSize  每页大小
     * @return 商家分页集合
     */
    public PageInfo<Business> selectPage(Business business, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<Business> list = businessMapper.selectAll(business);
        return PageInfo.of(list);
    }

    /**
     * 新增商家
     * @param business 传入的要插入的商家数据
     */
    public void add(Business business) {
        //首先判断用户账号在数据库中是否存在，如果存在则不能再插入相同的账号
        Business dbBusiness = this.selectByUserName(business.getUsername());
        if (ObjectUtil.isNotEmpty(dbBusiness)){
            throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
        }
        business.setRole(RoleEnum.BUSINESS.name());
        businessMapper.insert(business);

        List<Business> businesses = this.selectAll(null);
        for (Business b : businesses) {
            RedisUtils.setCacheObject(RedisConstants.REDIS_BUSINESS_KEY+b.getId(),b);
        }
        RedisUtils.setCacheObject(RedisConstants.REDIS_ALL_BUSINESS_KEY,businesses);

    }


    /**
     * 根据id删除商家数据
     * @param id 要删除的商家id
     */
    @Transactional
    public void deleteById(Integer id) {
        businessMapper.deleteById(id);
        RedisUtils.deleteObject(RedisConstants.REDIS_BUSINESS_KEY+id);
        List<Business> businesses = this.selectAll(null);
        for (Business b : businesses) {
            RedisUtils.setCacheObject(RedisConstants.REDIS_BUSINESS_KEY+b.getId(),b);
        }
        RedisUtils.setCacheObject(RedisConstants.REDIS_ALL_BUSINESS_KEY,businesses);
       bannerService.deleteByBusinessId(id);
       //根据businessId进行查询订单列表（查看是否还有订单）
        List<Orders> orders = ordersService.selectByBusinessId(id);
        for (Orders order : orders) {
            Integer orderId = order.getId();
            ordersService.deleteById(orderId);
            ordersItemService.deleteByOrderId(orderId);
        }
        //删除商品信息
        goodsService.deleteByBusinessId(id);
        //删除商品分类信息
        categoryService.deleteByBusinessId(id);
    }

    /**
     * 批量删除商家数据
     * @param ids 需要删除的多个id
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            this.deleteById(id);
        }
    }

    /**
     * 更新商家接口
     * @param business 传入的business
     */
    public void update(Business business) {
        //先根据id判断商家是否存在
        Business dbBusiness1 = this.selectById(business.getId());
        if (ObjectUtil.isEmpty(dbBusiness1)){
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        //判断要修改的账号在数据库中是否有重复
        Business dbBusiness2 = this.selectByUserName(business.getUsername());
        if (ObjectUtil.isNotEmpty(dbBusiness2) && !Objects.equals(dbBusiness2.getId(), business.getId())) {
            throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
        }
        businessMapper.updateById(business);

        List<Business> businesses = this.selectAll(null);
        for (Business b : businesses) {
            RedisUtils.setCacheObject(RedisConstants.REDIS_BUSINESS_KEY+b.getId(),b);
        }
        RedisUtils.setCacheObject(RedisConstants.REDIS_ALL_BUSINESS_KEY,businesses);
    }

    //商家注册
    public void register(Account account) {
        Business business = new Business();
        BeanUtils.copyProperties(account,business);
        if (ObjectUtil.isEmpty(account.getName())){
            business.setName(account.getUsername());
        }
        this.add(business);
    }

    //商家登录
    public Account login(Account account) {
        Business dbBusiness = this.selectByUserName(account.getUsername());
        if (ObjectUtil.isNull(dbBusiness)){
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        if (!account.getPassword().equals(dbBusiness.getPassword())){
            throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
        }
        //生成token
        String tokenData = dbBusiness.getId() + "-" + RoleEnum.BUSINESS.name();
        String token = TokenUtils.createToken(tokenData, dbBusiness.getPassword());
        dbBusiness.setToken(token);
        return dbBusiness;
    }

    //修改商家密码
    public void updatePassword(Account account) {
        Business dbBusiness = this.selectByUserName(account.getUsername());
        if (ObjectUtil.isNull(dbBusiness)){
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        if (!account.getPassword().equals(dbBusiness.getPassword())){
            throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR);
        }
        dbBusiness.setPassword(account.getNewPassword());
        businessMapper.updateById(dbBusiness);

        List<Business> businesses = this.selectAll(null);
        for (Business b : businesses) {
            RedisUtils.setCacheObject(RedisConstants.REDIS_BUSINESS_KEY+b.getId(),b);
        }
        RedisUtils.setCacheObject(RedisConstants.REDIS_ALL_BUSINESS_KEY,businesses);
    }
}
